package com.zxn.service;

import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import com.zxn.model.PointData;
import com.zxn.utils.ElasticUtils;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.geo.ShapeRelation;
import org.elasticsearch.common.geo.builders.CoordinatesBuilder;
import org.elasticsearch.common.geo.builders.LineStringBuilder;
import org.elasticsearch.common.geo.builders.PolygonBuilder;
import org.elasticsearch.common.geo.builders.ShapeBuilders;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.query.GeoBoundingBoxQueryBuilder;
import org.elasticsearch.index.query.GeoShapeQueryBuilder;
import org.elasticsearch.index.query.MatchPhraseQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.reindex.BulkByScrollResponse;
import org.elasticsearch.index.reindex.DeleteByQueryAction;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSONObject;
import com.vividsolutions.jts.geom.Coordinate;
import com.xiaoleilu.hutool.lang.Validator;

import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class WorkPositionDataProcessService {
   
	/**
	 * 添加区域到es中进行存储
	 * @param areaName
	 * @param areaId
	 * @param position
	 */
	public void addAreaToElastic(String areaName,String areaId, String position){
		
		//String position ="120.513554_30.724974,120.443127_30.687962,120.50723_30.648202,120.521028_30.675788,120.521315_30.677527";
		//String name ="区域1";
		//Long id=23423L;
		TransportClient client = ElasticUtils.getClient();
		String[] str = position.split(",");
		CoordinatesBuilder cdb = new CoordinatesBuilder();
		Double begin= (double)0,end=(double) 0;
		for (int i = 0; i < str.length; i++) {
			String[] p = str[i].split("_");
			try {
				if (i==0) {
					begin = Double.parseDouble(p[0]);
					end = Double.parseDouble(p[1]);
				}
				System.out.println(Double.parseDouble(p[0]));
				cdb.coordinate(Double.parseDouble(p[0]),Double.parseDouble(p[1]));				
			} catch (Exception e) {
				e.printStackTrace();
			}			
			
		}
		if (begin!=(double)0) {
			cdb.coordinate(begin, end);
		}
		
		
		try {			
			PolygonBuilder area =	ShapeBuilders.newPolygon(cdb);
			System.out.println(area);
			System.out.println(area.build());						
		    if(!ElasticUtils.isExists("workposition")){

		    	XContentBuilder mapping = XContentFactory.jsonBuilder()
		    			                  .startObject()
		    			                   .startObject("properties")
		    			                   .startObject("name").field("type","keyword").endObject()
		    			                   .startObject("id").field("type","keyword").endObject()
		    			                   .startObject("positions").field("type","keyword").endObject()
		    			                   .startObject("type").field("type","keyword").endObject()
		    			                   .startObject("location").field("type", "geo_shape").field("precision","50m").endObject()
		    			                   .endObject()
		    			                  .endObject();
		    	CreateIndexRequestBuilder cib = ElasticUtils.getAdminClient().prepareCreate("workposition");
		    	cib.addMapping("position", mapping);
		    	cib.get();
		   }
		   IndexResponse response = client.prepareIndex("workposition", "position")
                .setSource(jsonBuilder().startObject()
                		   .field("name",areaName)
                		   .field("id",areaId)
                		   .field("positions",position)
                		   .field("type","area")
                		   .field("location",area)
                		   .endObject()
                		   )
                .get();
		System.out.println(response.getResult());
		} catch (Exception e) {
			e.printStackTrace();		
		}		
	}
	
	/**
	 *  添加线段到es中进行存储
	 * @param lineName
	 * @param lineId
	 * @param position
	 */
	public void addLineToElastic(String lineName,String lineId, String position){
		TransportClient client = ElasticUtils.getClient();		
		String[] str = position.split(",");
		CoordinatesBuilder cdb = new CoordinatesBuilder();		
		for (int i = 0; i < str.length; i++) {
			String[] p = str[i].split("_");
			try {			
				cdb.coordinate(Double.parseDouble(p[0]),Double.parseDouble(p[1]));				
			} catch (Exception e) {
				e.printStackTrace();
			}			
			
		}	
		try {			
			LineStringBuilder area = ShapeBuilders.newLineString(cdb);
		    if(!ElasticUtils.isExists("workposition")){
		    	XContentBuilder mapping = XContentFactory.jsonBuilder()
		    			                  .startObject()
		    			                   .startObject("properties")
		    			                   .startObject("name").field("type","keyword").endObject()
		    			                   .startObject("id").field("type","keyword").endObject()
		    			                   .startObject("positions").field("type","keyword").endObject()
		    			                   .startObject("type").field("type","keyword").endObject()
		    			                   .startObject("location").field("type", "geo_shape").field("precision","50m").endObject()
		    			                   .endObject()
		    			                  .endObject();
		    	CreateIndexRequestBuilder cib = ElasticUtils.getAdminClient().prepareCreate("workposition");
		    	cib.addMapping("position", mapping);
		    	cib.get();
		   }
		   IndexResponse response = client.prepareIndex("workposition", "position")
                .setSource(jsonBuilder().startObject()
                		   .field("name",lineName)
                		   .field("id",lineId)
                		   .field("positions",position)
                		   .field("type","line")
                		   .field("location",area)
                		   .endObject()
                		   )
                .get();
		} catch (Exception e) {
			e.printStackTrace();		
		}		
	}
	
	/**
	 * 通过经纬度查询区域路段数据
	 * @param lgitude
	 * @param latitude
	 * @return
	 */
	public String  queryWorkPositionElastic(Double lgitude,Double latitude){
		try {
			TransportClient client = ElasticUtils.getClient();
			GeoShapeQueryBuilder qb = QueryBuilders.geoShapeQuery("location",ShapeBuilders.newPoint(new Coordinate(lgitude,latitude)));
			qb.relation(ShapeRelation.CONTAINS);
			SearchResponse response= client.prepareSearch("workposition").setTypes("position")
			      .setQuery(qb)
			      .execute().actionGet();
			
		  SearchHits hits = response.getHits();
		  String roadIds ="";
		  for (SearchHit searchHit : hits) {
			  Map<String,Object> map =searchHit.getSource();
			  if(roadIds.isEmpty()){				  
				  roadIds=roadIds+map.get("id");
			  }else{
				  roadIds=roadIds+";"+map.get("id");
			  }
		  }		 
		  return roadIds;
		} catch (Exception e) {
			log.error("通过经纬度查询区域路段数据异常",e);
		  return null;
		}
	}
	/**
	 * 根据id删除es的区域位置数据
	 * @param id
	 * @return
	 */
	public Long deleteWorkPositionById(String id){
		BulkByScrollResponse response = DeleteByQueryAction.INSTANCE.newRequestBuilder(ElasticUtils.getClient())
                                                            .filter(QueryBuilders.matchQuery("id", id))
                                                            .source("workposition")
                                                            .get();
		long deleted = response.getDeleted();				
		if(deleted == 1){
			log.info("es删除区域位置成功");
		}else{
			log.info("es删除区域位置失败");
		}
	    return deleted;
	 }
	
	
	/**
	 * 位置点数据添加到es中
	 * @param lgitude
	 * @param latitude
	 */
    public void addPointDataToElastic(String id,String pointName,Double lgitude,Double latitude){
		
		
		try {		
			TransportClient client = ElasticUtils.getClient();			
			GeoPoint geoPoint = new GeoPoint(latitude, lgitude);
			
		    if(!ElasticUtils.isExists("point_data")){

		    	XContentBuilder mapping = XContentFactory.jsonBuilder()
		    			                  .startObject()
		    			                   .startObject("properties")
		    			                   .startObject("name").field("type","keyword").endObject()
		    			                   .startObject("id").field("type","keyword").endObject()
		    			                   .startObject("lgitude").field("type","keyword").endObject()
		    			                   .startObject("latitude").field("type","keyword").endObject()
		    			                   .startObject("location").field("type", "geo_point").endObject()
		    			                   .endObject()
		    			                  .endObject();
		    	CreateIndexRequestBuilder cib = ElasticUtils.getAdminClient().prepareCreate("point_data");
		    	cib.addMapping("position", mapping);
		    	cib.get();
		   }
		   IndexResponse response = client.prepareIndex("point_data", "position")
                .setSource(jsonBuilder().startObject()
									    .field("id",id)
									    .field("name",pointName)
									    .field("lgitude",String.valueOf(lgitude))
									    .field("latitude",String.valueOf(latitude))
									    .field("location",geoPoint)
                		   .endObject()
                		   )
                .get();
		  log.info("点存储Elastic结果:{}", response.getResult());
		} catch (Exception e) {
			e.printStackTrace();		
		  log.info("点存储Elastic结果失败");
		}		
	}
    /**
     * 删除点数据
     * @param
     */
    public void deletePointData(String id){
    	BulkByScrollResponse response = DeleteByQueryAction.INSTANCE.newRequestBuilder(ElasticUtils.getClient())
			                                .filter(QueryBuilders.matchQuery("id", id)) 
			                                .source("point_data")
			                                .get();                                             
		long deleted = response.getDeleted();				
		if(deleted == 1){
			log.info("es删除点成功：{}",id);
		}else{
			log.info("es删除点失败:{}",id);
		}
    }
    /**
     * 通过区域查询点数据
     * @param lgitude1
     * @param latitude1
     * @param lgitude2
     * @param latitude2
     */
    public List<PointData> queryPointData(Double latitude1,Double lgitude1,Double latitude2,Double lgitude2,String type){
        TransportClient  client = ElasticUtils.getClient();		
		GeoBoundingBoxQueryBuilder queryBuilder = QueryBuilders.geoBoundingBoxQuery("location")                          
                                                               .setCorners(latitude1,lgitude1, 
                                                            		   latitude2, lgitude2); 
		
		///QueryBuilders.boolQuery().must(queryBuilder).must(qName);
		SearchResponse response  =null;
		if(Validator.isNotEmpty(type)){		
			MatchPhraseQueryBuilder qName = QueryBuilders.matchPhraseQuery("type", type);  
			response = client.prepareSearch("point_data")
					.setSize(1000)
					.setQuery(QueryBuilders.boolQuery()
							.must(queryBuilder)
							.must(qName))				                      
					.get();
		 }else{
			 response = client.prepareSearch("point_data")
						.setSize(1000)
						.setQuery(QueryBuilders.boolQuery()
								.must(queryBuilder))									                      
						.get();
		 }
		SearchHits hits = response.getHits();
		List<PointData> datas = new ArrayList<>();
		for (SearchHit searchHit : hits) {
			PointData vo = JSONObject.parseObject(searchHit.getSourceAsString(), PointData.class);
			datas.add(vo);
		}
		return datas;
    }
	
	
}
